package com.magold.io;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SimpleXMLReaderWriter extends SimpleXMLWriter implements XMLReader {

	@Override
	public String getTextContent() {
		String txt = currNode.getTextContent();
		debug("XML-" + currNode.getNodeName(), "Retrieved text content: " + txt);
		
		return txt;
	}

	@Override
	public String getString(String key) {
		if (!(currNode instanceof Element)) {
			throw new IllegalStateException("current node is not a Element.");
		}
		
		String value = ((Element) currNode).getAttribute(key);
		debug("XML-" + currNode.getNodeName(), "Retrieved value: " + value + " @ key: " + key);
		
		return value.equals("") ? null : value;
	}

	@Override
	public int getInt(String key) {
		return Integer.parseInt(getString(key));
	}

	@Override
	public float getFloat(String key) {
		return Float.parseFloat(getString(key));
	}

	@Override
	public double getDouble(String key) {
		return Double.parseDouble(getString(key));
	}

	@Override
	public byte getByte(String key) {
		return Byte.parseByte(getString(key));
	}

	@Override
	public boolean getBoolean(String key) {
		return Boolean.parseBoolean(getString(key));
	}

	@Override
	public boolean moveToRootElement() {
		// move to document node.
		Node buf = currNode;
		resetCursor();
		
		NodeList children = currNode.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node n = children.item(i);
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				currNode = n;
				debug("XML-" + currNode.getNodeName(), "move to root element successfully.");
				return true;
			}
		}
		
		debug("XML-" + currNode.getNodeName(), "not find root element, you should create it first.");
		currNode = buf;
		return false;
	}

	@Override
	public boolean moveToNextSibling() {
		Node next = currNode.getNextSibling();
		if (next != null) {
			debug("XML-" + currNode.getNodeName(), "cursor: " + currNode.getNodeName() + " -> " + next.getNodeName() + " for nextSibling.");
			currNode = next;
			return true;
		}
		
		debug("XML" + currNode.getNodeName(), "no more sibling.");
		return false;
	}
	
	@Override
	public boolean moveToFirstChild() {
		NodeList children = currNode.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node n = children.item(i);
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				currNode = n;
				debug("XML-" + currNode.getNodeName(), "move to first child successfully.");
				return true;
			}
		}
		
		debug("XML" + currNode.getNodeName(), "no child.");
		return false;
	}

	@Override
	public String getNodeName() {
		return currNode.getNodeName();
	}
	
	@Override
	public int getChildElementCount() {
		int count = 0;
		
		NodeList children = currNode.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node n = children.item(i);
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				count++;
			}
		}
		
		return count;
	}

	@Override
	public boolean getBoolean(String key, boolean pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return Boolean.parseBoolean(value);
		}
	}

	@Override
	public String getString(String key, String pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return value;
		}
	}

	@Override
	public double getDouble(String key, double pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return Double.parseDouble(value);
		}
	}

	@Override
	public float getFloat(String key, float pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return Float.parseFloat(value);
		}
	}

	@Override
	public byte getByte(String key, byte pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return Byte.parseByte(value);
		}
	}

	@Override
	public int getInt(String key, int pDefault) {
		String value = getString(key);
		if (value == null) {
			return pDefault;
		} else {
			return Integer.parseInt(value);
		}
	}
	
	@Override
	public int traverseChildren(ElementTranversalCallback pCallback) {
		int count = 0;
		if (moveToFirstChild()) {
			do {
				if (currNode.getNodeType() == Node.ELEMENT_NODE && pCallback.onAccessChild(this)) {
					count++;
				}
			} while (moveToNextSibling());
			
			moveToParent();
		}
		
		return count;
	}

}
